package com.tdp.dblp;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;


public class DblpParser {
	private Connection conn;
	/**
	 *当前元素
	 */
	private int curElement = -1;
	/**
	 * 祖先元素
	 */
	private int ancestor = -1;
	private Conference conf;
	int line = 0;
	PreparedStatement  stmt_authorpaper;
	int errors = 0;
	StringBuffer author;
	
	DblpParser(String uri) throws SQLException {
		try {
			System.out.println("Parsing...");
			conn = DBConnection.getConn();
			conn.setAutoCommit(false);
			stmt_authorpaper = conn
					.prepareStatement("insert into authorpaper(author,conference,year,conf_key) values(?,?,?,?)");
			SAXParserFactory parserFactory = SAXParserFactory.newInstance();
			SAXParser parser = parserFactory.newSAXParser();
			ConfigHandler handler = new ConfigHandler();
//			parser.getXMLReader().setFeature(
//					"http://xml.org/sax/features/validation", true);
			parser.parse(new File(uri), handler);
			//execute sql
			try {
				stmt_authorpaper.executeBatch();
				conn.commit();
//				System.out.println("Processed " + line);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn.close();
			System.out.println("num of errors: " + errors);
		} catch (IOException e) {
			System.out.println("Error reading URI: " + e.getMessage());
		} catch (SAXException e) {
			System.out.println("Error in parsing: " + e.getMessage());
		} catch (ParserConfigurationException e) {
			System.out.println("Error in XML parser configuration: "
					+ e.getMessage());
		}
	}
	private class ConfigHandler extends DefaultHandler {
		
		public void startElement(String namespaceURI, String localName,
				String rawName, Attributes atts) throws SAXException {
			if (rawName.equals("inproceedings")) {
				ancestor = Elements.INPROCEEDINGS;
				curElement = Conference.INPROCEEDINGS;
				conf = new Conference();
				conf.conf_key=atts.getValue("key");
			} else if (rawName.equals("author") && ancestor == Elements.INPROCEEDINGS) {
				author = new StringBuffer();
			}
			if(ancestor == Elements.INPROCEEDINGS)
				curElement=Conference.getElement(rawName);
			else if(ancestor==-1)
				curElement=0;
			line++;
		}

		public void characters(char[] ch, int start, int length)
				throws SAXException {
			if (ancestor == Elements.INPROCEEDINGS) {
				String str = new String(ch, start, length).trim();
				if(str.length()>0)
				{
//					System.out.println("STR_"+str);
				if (curElement == Conference.AUTHOR) {
//					System.out.println("author_"+str);
					author.append(str);
				} else if (curElement == Conference.BOOKTITLE) {
//					System.out.println("booktitle_"+str);
					conf.booktitle = str;
				}  else if (curElement == Conference.YEAR) {			
					conf.year = Integer.parseInt(str.trim());
				}
				}
			} 
		}

		public void endElement(String namespaceURI, String localName,
				String rawName) throws SAXException {
//			System.out.println("结束处理元素"+rawName);
			if (rawName.equals("author") && ancestor == Elements.INPROCEEDINGS) {
				conf.authors.add(author.toString().trim());
			}
			
			if (rawName.equals("inproceedings")) {
				ancestor = -1;
				try {
					if (conf.booktitle.equals(null)|| conf.year == 0) {
						System.out.println("Error in parsing " + conf);
						errors++;
						return;
					}
					for (String author : conf.authors) {
						stmt_authorpaper.setString(1, author);
						stmt_authorpaper.setString(2, conf.booktitle);
						stmt_authorpaper.setInt(3, conf.year);
						stmt_authorpaper.setString(4, conf.conf_key);
						stmt_authorpaper.addBatch();
					}

				} catch (SQLException e) {
					e.printStackTrace();
					System.out.println("line:" + line);
					System.exit(0);
				}
			} 

			if (line % 10000 == 0) {
				try {
					stmt_authorpaper.executeBatch();
					conn.commit();
					//System.out.println("Processing " + line);
				} catch (SQLException e) {
					System.err.println(e.getMessage());
				}
			}
		}

		private void Message(String mode, SAXParseException exception) {
			System.out.println(mode + " Line: " + exception.getLineNumber()
					+ " URI: " + exception.getSystemId() + "\n" + " Message: "
					+ exception.getMessage());
		}

		public void warning(SAXParseException exception) throws SAXException {
			Message("**Parsing Warning**\n", exception);
			throw new SAXException("Warning encountered");
		}

		public void error(SAXParseException exception) throws SAXException {
			Message("**Parsing Error**\n", exception);
			throw new SAXException("Error encountered");
		}

		public void fatalError(SAXParseException exception) throws SAXException {
			Message("**Parsing Fatal Error**\n", exception);
			throw new SAXException("Fatal Error encountered");
		}
	}



	public static void main(String[] args) throws SQLException,
			ClassNotFoundException {
		Long start = System.currentTimeMillis();
		String file = "src/db1.xml";
		DblpParser p = new DblpParser(file);
		Long end = System.currentTimeMillis();
		System.out.println("Used: " + (end - start) / 1000 + " seconds");
	}
}
